package learning.spring.binarytea;

import org.springframework.beans.factory.ObjectProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.JdbcUserDetailsManager;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.OrRequestMatcher;
import org.springframework.web.servlet.mvc.UrlFilenameViewController;

import javax.sql.DataSource;
import java.util.Objects;

@Configuration
@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Bean("/login")
    public UrlFilenameViewController loginController() {
        UrlFilenameViewController controller = new UrlFilenameViewController();
        controller.setSupportedMethods(HttpMethod.GET.name());
        controller.setSuffix(".html");
        return controller;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/").permitAll()
                .mvcMatchers("/actuator/*").permitAll()
                .anyRequest().authenticated().and()
                .formLogin()
                .loginPage("/login").permitAll()
                .defaultSuccessUrl("/order")
                .failureUrl("/login")
                .loginProcessingUrl("/doLogin")
                .usernameParameter("user")
                .passwordParameter("pwd").and()
                .httpBasic().and()
                .logout()
                .logoutSuccessUrl("/")
                .logoutRequestMatcher(new OrRequestMatcher(
                        new AntPathRequestMatcher("/logout", "GET"),
                        new AntPathRequestMatcher("/logout", "POST")));
    }

    @Bean
    public UserDetailsService userDetailsService(ObjectProvider<DataSource> dataSources, ObjectProvider<PasswordEncoder> passwordEncoder) {
        JdbcUserDetailsManager userDetailsManager = new JdbcUserDetailsManager();
        userDetailsManager.setDataSource(Objects.requireNonNull(dataSources.getIfAvailable()));

        // 首先从Spring上下文中获取Encoder，如果没有创建一个 -- 此时获取的是 BCryptPasswordEncoder 编码类
        PasswordEncoder encoder = passwordEncoder.getIfAvailable(PasswordEncoderFactories::createDelegatingPasswordEncoder);

        // 新建用户
        UserDetails userDetails = User.builder()
                .username("scf2")
                // .password("{bcrypt}$2a$10$iAty2GrJu9WfpksIen6qX.vczLmXlp.1q1OHBxWEX8BIldtwxHl3u")// 此密文不对
                // .password("{bcrypt}$2a$10$2Bk.lnrnd4H2zGW/GMPg8OeF/XaVX0fZXIevtVZG9CuUy2xkgHVyS")// 此密文是实际生成的
                .password("showmethemoney")// 明文密码
                .passwordEncoder(encoder::encode)// 密码加密
                .authorities("READ_ORDER", "WRITE_ORDER")
                .build();
        // 实时添加用户到mysql数据库
        userDetailsManager.createUser(userDetails);

        return userDetailsManager;
    }

}
